package com.rrd.hive.udf.iptoarea;

import java.io.IOException;
import java.io.RandomAccessFile;

public class RRDAreaFile {
    private static final int IP_RECORD_LENGTH = 7;
    private RandomAccessFile ipFile = null;

    public RandomAccessFile getIpFile() {
        return this.ipFile;
    }

    private static RRDAreaFile instance = null;

    public RRDAreaFile(String ipFilePath) {
        try {
            if (null == ipFilePath) {
                System.exit(1);
            }
            this.ipFile = new RandomAccessFile(ipFilePath, "r");
        } catch (IOException e) {
            System.out.println("Can not open file " + ipFilePath + ".");
        }
    }

    public void closeIpFile(RandomAccessFile ipFile) {
        try {
            ipFile.close();
            ipFile = null;
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (null != ipFile) {
                ipFile = null;
            }
        }
    }

    public synchronized static RRDAreaFile getInstance(String ipFilePath) {
        if (null == RRDAreaFile.instance) {
            RRDAreaFile.instance = new RRDAreaFile(ipFilePath);
        }
        return RRDAreaFile.instance;
    }

    public RRDAreaRecord find(String ip, RandomAccessFile ipFile) {
        long ipValue = Utils.ipToLong(ip);
        RRDAreaHeader header = new RRDAreaHeader(ipFile);
        long first = header.getIpBegin();
        int left = 0;
        int right = (int) ((header.getIpEnd() - first)
            / RRDAreaFile.IP_RECORD_LENGTH);
        int middle = 0;
        RRDAreaIndex middleIndex = null;
        // 二分查找
        while (left <= right) {
            // 无符号右移，防止溢出
            middle = left + right >>> 1;
            middleIndex = new RRDAreaIndex(ipFile,
                first + middle * RRDAreaFile.IP_RECORD_LENGTH);
            if (ipValue > middleIndex.getStartIp()) {
                left = middle + 1;
            } else if (ipValue < middleIndex.getStartIp()) {
                right = middle - 1;
            } else {
                return new RRDAreaRecord(ipFile, middleIndex.getStartIp(),
                    middleIndex.getIpPos());
            }
        }
        // 找不到精确的，取在范围内的
        middleIndex = new RRDAreaIndex(ipFile,
            first + right * RRDAreaFile.IP_RECORD_LENGTH);
        RRDAreaRecord record = new RRDAreaRecord(ipFile,
            middleIndex.getStartIp(), middleIndex.getIpPos());
        if (ipValue >= record.getBeginIP() && ipValue <= record.getEndIP()) {
            return record;
        } else {
            // 找不到相应的记录
            return new RRDAreaRecord(0L, ipValue);
        }
    }
}
